home *** CD-ROM | disk | FTP | other *** search
- ;* SEARCH.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* String searching capabilities (interpreter support) *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL medium
- LOCALS @@
-
- INCLUDE "scheme.ash"
- INCLUDE "interprt.ash"
-
- CODESEG
- ;************************************************************************
- ;* Substring-Find-Next-String *
- ;************************************************************************
- PROC C str_srch_str USES si di, @@string, @@start, @@end, @@match, @@direction, @@case_s
- LOCAL @@stradr, @@length
-
- cld ; for now, assume forward
- mov bx, [@@string]
- mov di, [(REG bx).page]
- cmp [ptype+di], STRTYPE ; is source string a string?
- je @@stringok
- @@toerror:
- jmp @@error
- @@stringok:
- ldpage es, di
- mov di, [(REG bx).disp]
- sstrlen ax, <es:di>
- mov [@@length], ax
- lea di, [(STRDEF di).buffer]
- mov [@@stradr], di
- mov bx, [@@start]
- call getnum
- jc @@toerror
- add di, ax
- mov cx, ax
- mov bx, [@@end]
- call getnum
- jc @@toerror
- cmp ax, [@@length] ; test ending offset against string length
- ja @@toerror
- sub ax, cx ; ax = end - start
- jb @@toerror
- mov bx, [@@match]
- mov si, [(REG bx).page]
- cmp [ptype+si], STRTYPE ; this is a string, isn't it?
- jne @@toerror
-
- push ds es
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen dx, <es:si>
- lea si, [(STRDEF si).buffer]
- sub dx, 1 ; dx = strlen(match) - 1
- jnb @@not_empty
- pop es
- xor si, si ; if empty string, already found
- jmp @@found
- @@not_empty:
- mov [@@length], dx
- mov cx, ax
- sub cx, dx ; cx = number of tries to do
- jnbe @@search
- pop es
- jmp @@notfound
-
- @@search:
- cmp [@@direction], 0 ; if backward...
- jz @@fwd
- add di, ax ; start from end of strings
- add si, dx
- std
- @@fwd:
- push es
- pop ds es ;-------------------------------- DS changed ! \\\
- lodsb ; read "1st" char of "match"
- cmp [@@case_s], 0
- jz @@insensitive
-
- @@sensitive:
- jcxz @@notfound
- repnz scasb ; locate first char of match in str
- jnz @@notfound
- or dx, dx ; single-char target ?
- jz @@locate_ofs
- push cx si di
- mov cx, dx ; verify other chars
- repz cmpsb
- pop di si cx
- jnz @@sensitive
-
- @@locate_ofs:
- mov si, di
- scasb ; one step forward -> one step back
- sub di, si
- jnb @@forw
- sub si, dx
- @@forw:
- sub si, di
- sub si, [@@stradr]
- @@found:
- pop ds
- mov bx, [@@string] ; load address of destination register
- call retnum
- jmp @@done
- @@notfound:
- pop ds
- xor ax, ax ; store nil in the
- mov bx, [@@string] ; destination register
- mov [(REG bx).bpage], al
- mov [(REG bx).disp], ax
- @@done:
- xor ax, ax
- @@return:
- ret
-
- @@insensitive:
- lea bx, [locases]
- xlat [ss:bx]
- mov ah, al
- @@loop_ci:
- jcxz @@notfound
- @@scan_ci: ; locate first char of match in str
- mov al, [es:di]
- scasb ; di += (if DF -1 1)
- xlat [ss:bx]
- cmp al, ah
- loopnz @@scan_ci
- jnz @@notfound
- or dx, dx ; single-char target ?
- jz @@locate_ofs
- push ax cx si di
- mov cx, dx ; verify other chars
- @@comp_ci:
- lodsb
- xlat [ss:bx]
- mov ah, al
- mov al, [es:di]
- scasb ; di += (if DF -1 1)
- xlat [ss:bx]
- cmp al, ah
- loopz @@comp_ci
- pop di si cx ax
- jnz @@loop_ci
- jmp @@locate_ofs
-
- @@error:
- cmp [@@direction], 0 ; search forward or backward?
- jnz @@backerror
- lea ax, [@@msgfwd]
- DATASEG
- @@msgfwd DB "SUBSTRING-FIND-NEXT-STRING", 0
- CODESEG
- jmp @@allerrors
-
- @@backerror:
- lea ax, [@@msgprv]
- DATASEG
- @@msgprv DB "SUBSTRING-FIND-PREVIOUS-STRING", 0
- CODESEG
-
- @@allerrors:
- mov bx, 4 ; load VM argument count
- call set_src_error C, ax, bx, [@@string], [@@start], [@@end], [@@match]
- mov ax, -1 ; load "invalid operand" flag
- jmp @@return
- ENDP str_srch_str
-
- ;************************************************************************
- ;* Substring-Find-Next-Char-in-Set *
- ;************************************************************************
- PROC C srch_str USES si di, @@string, @@start, @@end, @@charset, @@direction
- LOCAL @@stradr:dword, @@length, @@endofs, @@startofs
-
- cld ; for now, assume forward
- mov cx, [@@direction] ; set search direction
- mov bx, [@@string]
- mov si, [(REG bx).page]
- cmp [ptype+si], STRTYPE ; is source string a string?
- je @@stringok
- @@toerror:
- jmp @@error
- @@stringok:
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen ax, <es:si>
- mov [@@length], ax
- lea si, [(STRDEF si).buffer]
- mov [WORD LOW @@stradr], si
- mov [WORD HIGH @@stradr], es
- mov bx, [@@start]
- call getnum
- jc @@toerror
- mov [@@startofs], ax
- mov bx, [@@end]
- call getnum
- jc @@toerror
- cmp [@@startofs], ax ; is starting offset greater than ending?
- ja @@toerror
- cmp ax, [@@length] ; test ending offset against string length
- ja @@toerror
- mov [@@endofs], ax
- mov bx, [@@charset]
- mov di, [(REG bx).page]
- cmp [ptype+di], STRTYPE ; this is a string, isn't it?
- jne @@char
- ldpage es, di
- mov di, [(REG bx).disp]
- sstrlen dx, <es:di>
- lea di, [(STRDEF di).buffer]
- jmp @@strset
- @@char:
- cmp di, SPECCHAR*2 ; is charset argument a single character?
- je @@singlechar
- jmp @@toerror
-
- @@singlechar:
- mov al, [byte (REG bx).disp]
- les di, [@@stradr]
- mov dx, cx ; save direction indicator in dx
- mov cx, [@@endofs] ; compute length of search string
- sub cx, [@@startofs]
- je @@charnotfound ; if search length is zero, return 'nil
- or dx, dx
- jnz @@backchar
- add di, [@@startofs] ; compute address of start of substring
- repne scasb ; search for single character
- jne @@charnotfound
- dec di ; fix up ending index
- jmp @@skip
- @@backchar:
- add di, [@@endofs] ; compute address of end of substring
- dec di
- std ; set search direction to be backwards
- repne scasb
- cld
- jne @@charnotfound
- inc di ; fix up ending index
- @@skip:
- mov si, di ; copy character address to si
- sub si, [WORD LOW @@stradr] ; and compute found character's address
- jmp @@found
-
- @@strset:
- push ds ; save the data segment address
- or cx, cx ; in which direction are we to search?
- jz @@forwardstr
-
- ;Register Usage in Innermost Loop:
- ; ds:si - pointer to next character in source string
- ; es:di - pointer to charset string
- ; al - search character
- ; bx - ending offset (source string)
- ; cx - length of charset string
- ; dx - length of charset string (used to refresh cx)
-
- mov bx, [WORD LOW @@stradr] ; compute ending offset for string
- add bx, [@@startofs]
- lds si, [@@stradr]
- add si, [@@endofs] ; and compute end of substring address
- jmp @@startback
-
- @@loopback:
- sub di, dx ; reset starting offset of charset string
- @@startback:
- cmp si, bx ; at beginning of substring?
- jbe @@strnotfound
- mov cx, dx ; reload charset string length
- dec si ; decrement source string index
- mov al, [si]
- repne scasb
- jne @@loopback
- pop ds
- sub si, [WORD LOW @@stradr] ; compute index of current character
- jmp @@found
-
- @@strnotfound:
- pop ds
- @@charnotfound:
- xor ax, ax ; store nil in the
- mov bx, [@@string] ; destination register
- mov [(REG bx).bpage], al
- mov [(REG bx).disp], ax
- jmp @@done
-
- @@forwardstr:
- mov bx, [WORD LOW @@stradr] ; compute ending offset for string
- add bx, [@@endofs]
- lds si, [@@stradr]
- add si, [ss:@@startofs] ; compute beginning of substring
- jmp @@startforward
-
- @@loopforward:
- sub di, dx ; reset starting offset of charset string
- @@startforward:
- cmp si, bx ; at end of source string?
- jae @@strnotfound
- mov cx, dx ; reload charset string length
- lodsb
- repne scasb
- jne @@loopforward
- pop ds
-
- sub si, [WORD LOW @@stradr] ; adjust offset of character found
- dec si
- @@found:
- mov bx, [@@string] ; load address of destination register
- call retnum
- @@done:
- xor ax, ax ; set completion code for normal return
- @@return:
- ret
-
- @@error:
- or cx, cx ; search forward or backward?
- jnz @@backerror
- lea ax, [@@msgfwd]
- DATASEG
- @@msgfwd DB "SUBSTRING-FIND-NEXT-CHAR-IN-SET", 0
- CODESEG
- jmp @@allerrors
-
- @@backerror:
- lea ax, [@@msgprv]
- DATASEG
- @@msgprv DB "SUBSTRING-FIND-PREVIOUS-CHAR-IN-SET", 0
- CODESEG
-
- @@allerrors:
- mov bx, 4 ; load VM argument count
- call set_src_error C, ax, bx, [@@string], [@@start], [@@end], [@@charset]
- mov ax, -1 ; load "invalid operand" flag
- jmp @@return
- ENDP srch_str
-
- ;************************************************************************
- ;* al *
- ;* (string-length string) string-length d=s1 *
- ;* *
- ;* Purpose: Scheme Interpreter support for the "string-lengt" function.*
- ;************************************************************************
-
- PROC C st_len USES si, @@string
- mov bx, [@@string]
- mov si, [(REG bx).page]
- cmp [ptype+si], STRTYPE
- jne @@error
-
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen si, <es:si>
- call retnum
- xor ax, ax ; set error code for normal return
- @@return:
- ret
-
- @@error:
- lea ax, [@@msg]
- mov cx, 1 ; indicate one operand
- call set_src_error C, ax, cx, bx
- mov ax, -1 ; indicate error return
- jmp @@return
- DATASEG
- @@msg DB "STRING-LENGTH", 0
- CODESEG
- ENDP st_len
-
- ;************************************************************************
- ;* (%str-append str1 start1 end1 {nil,char,str2} str3 start3 end3) *
- ;************************************************************************
- PROC C str_apnd USES si di, @@end3, @@start3, @@str3, @@str2, @@end1, @@start1, @@str1
- LOCAL @@len3, @@len2, @@len1, @@offset3, @@offset1
-
- mov bx, [@@start1] ; validate string1
- call getnum
- jnc @@start1ok
- @@linkerror:
- jmp @@error
- @@start1ok:
- add ax, OFFSET (TYPE STRDEF).buffer
- mov [@@offset1], ax
- mov bx, [@@end1]
- call getnum
- jc @@linkerror
- add ax, OFFSET (TYPE STRDEF).buffer
- mov bx, [@@str1]
- mov si, [(REG bx).page]
- cmp [ptype+si], STRTYPE
- jne @@linkerror
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen cx, <es:si>, OVERHEAD
- cmp ax, cx ; is ending offset too big ?
- ja @@linkerror
- sub ax, [@@offset1] ; is ending offset too small?
- jb @@linkerror
- mov [@@len1], ax
-
- mov bx, [@@start3] ; validate string3
- call getnum
- jc @@error
- add ax, OFFSET (TYPE STRDEF).buffer
- mov [@@offset3], ax
- mov bx, [@@end3]
- call getnum
- jc @@error
- add ax, OFFSET (TYPE STRDEF).buffer
- mov bx, [@@str3]
- mov si, [(REG bx).page]
- cmp [ptype+si], STRTYPE
- jne @@error
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen cx, <es:si>, OVERHEAD
- cmp ax, cx ; is ending offset too big ?
- ja @@error
- sub ax, [@@offset3] ; is ending offset too small?
- jb @@error
- mov [@@len3], ax
-
- mov bx, [@@str2] ; validate string2, whatever it be
- mov si, [(REG bx).page]
- cmp si, NIL_PAGE*2 ; is string2 nil?
- jne @@notnil
- mov [@@len2], 0 ; nil has length 0
- jmp @@common
-
- @@error:
- mov ax, -1 ; signal error
- jmp @@return
-
- @@notnil:
- cmp si, SPECCHAR*2 ; is string2 a character?
- jne @@notchar
- mov [@@len2], 1 ; character has length 1
- jmp @@common
- @@notchar:
- cmp [ptype+si], STRTYPE ; is string2 a string?
- jne @@error
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen ax, <es:si>
- mov [@@len2], ax ; save string length for further testing
-
- @@common:
- mov ax, [@@len1] ; compute the length of the new string
- add ax, [@@len2]
- add ax, [@@len3]
- cmp ax, 4000h - OFFSET (TYPE STRDEF).buffer ; greater than max size?
- jge @@error
- mov bx, STRTYPE ; load tag=string
- lea cx, [tmp_reg]
- call alloc_block C, cx, bx, ax
- mov di, [tmp_reg.page] ; load pointer to newly allocated string
- ldpage es, di
- mov di, [tmp_reg.disp]
- lea di, [(STRDEF di).buffer]
- ; Move in data from all substrings
- mov cx, [@@len1]
- mov bx, [@@str1]
- mov si, [(REG bx).disp]
- add si, [@@offset1]
- mov bx, [(REG bx).page]
-
- push ds
- ldpage ds, bx
- rep movsb ; copy string1 into new string
- pop ds
-
- mov cx, [@@len2]
- or cx, cx ; any characters to move?
- je @@skipstring2
- mov bx, [@@str2]
- mov si, [(REG bx).disp]
- mov bx, [(REG bx).page]
-
- push ds
- cmp bl, SPECCHAR*2 ; is string2 a character?
- jne @@string2notchar
- mov si, [@@str2]
- jmp @@string2copy
- @@string2notchar:
- ldpage ds, bx
- lea si, [(STRDEF si).buffer]
- @@string2copy:
- rep movsb ; copy string2 into new string
- pop ds
-
- @@skipstring2:
- mov cx, [@@len3]
- mov bx, [@@str3]
- mov si, [(REG bx).disp]
- add si, [@@offset3]
- mov bx, [(REG bx).page]
-
- push ds
- ldpage ds, bx
- rep movsb ; copy string3 into new string
- pop ds
-
- mov di, [@@str1] ; return pointer to new string
- mov al, [tmp_reg.bpage]
- mov [(REG di).bpage], al
- mov ax, [tmp_reg.disp]
- mov [(REG di).disp], ax
- xor ax, ax ; ax nul = success
- @@return:
- ret
- ENDP str_apnd
-
- ;************************************************************************
- ;* Reify(!)-Stack *
- ;* *
- ;* Purpose: To provide the ability to manipulate items on the Scheme *
- ;* runtime stack from Scheme. *
- ;* *
- ;* Description: The elements of the stack are referenced by providing *
- ;* the byte offset of the desired element as an index *
- ;* to the REIFY-STACK or REIFY-STACK! instruction. An *
- ;* index of -1 to REIFY-STACK is a request that the current*
- ;* stack frame pointer be returned. *
- ;************************************************************************
- PROC C reif_stk USES si di, @@index, @@value, @@store
- mov bx, [@@index]
- cmp [@@store], 0 ; is this a REIFY-STACK operation?
- jne @@getdata
- ; index = -1 --> return frame pointer
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@getdata
- cmp [(REG bx).disp], -1
- jne @@getdata
- mov si, [frameptr]
- add si, [base] ; compute absolute offset
- call retnum
- jmp @@done
- @@getdata:
- call getnum
- jc @@error
- push ax
- xor dx, dx
- mov bx, SIZE POINTER
- div bx
- pop ax ; restore the byte index
- or dx, dx ; is it a multiple of POINTERs ?
- jnz @@error
- mov dx, [base] ; current top of stack (topofstack) offset
- add dx, [topofstack]
- cmp ax, dx ; is index larger than topofstack?
- ja @@error
- cmp ax, [base] ; is base < element index?
- jb @@incontinuation
- sub ax, [base] ; compute byte offset in stack buffer
- add ax, OFFSET s_stack
- mov si, ax
- push ds
- pop es ; desired element at [es:si]
- jmp @@doit ; fetch/store the element
-
- @@error:
- cmp [@@store], 0 ; is this a fetch or store?
- jne @@storeerror
- lea ax, [@@msgget]
- DATASEG
- @@msgget DB "%REIFY-STACK", 0
- CODESEG
- mov bx, 1 ; 1 operand
- jmp @@allerrors
-
- @@storeerror:
- lea ax, [@@msgput]
- DATASEG
- @@msgput DB "%REIFY-STACK!", 0
- CODESEG
- mov bx, 2 ; 2 operands
- push [@@value] ; and push second reigster operand
-
- @@allerrors:
- call set_src_error C, ax, bx, [@@index]
- mov ax, -1 ; load an error flag
- jmp @@ret
-
- @@incontinuation:
- mov bx, [prev_reg.page] ; make [es:si] point to the previous
- mov si, [prev_reg.disp] ; stack segment continuation object
- ldpage es, bx
- @@loop:
- cmp ax, [(CONTDEF es:si).base.val]; compare element index:continuation base
- jae @@found
- mov bl, [(CONTDEF es:si).stk.page]; load previous stack frame
- mov si, [(CONTDEF es:si).stk.disp]
- ldpage es, bx
- jmp @@loop
- @@found:
- sub ax, [(CONTDEF es:si).base.val]; subtrace off continuation's base
- add si, ax ; add entry's byte offset
- lea si, [(CONTDEF si).data]; adjust for continuation header
-
- @@doit: ; stack element address at [es:si]
- cmp [@@store], 0 ; test fetch/store flag
- jne @@dostore
- mov bx, [@@index]
- mov al, [(POINTER es:si).page]; read stack data
- mov [(REG bx).bpage], al
- mov ax, [(POINTER es:si).disp]
- mov [(REG bx).disp], ax
- jmp @@done
- @@dostore:
- mov bx, [@@value]
- mov al, [(REG bx).bpage]; write element to stack
- mov [(POINTER es:si).page], al
- mov ax, [(REG bx).disp]
- mov [(POINTER es:si).disp], ax
- @@done:
- xor ax, ax ; indicate no error encountered
- @@ret:
- ret
- ENDP reif_stk
-
- ;************************************************************************
- ;* al al ah al ah *
- ;* (%SUBSTRING-DISPLAY string start end row-bias window) *
- ;* *
- ;* Purpose: Special support for displaying strings to the CRT for *
- ;* applications such as text editors. *
- ;************************************************************************
- ; Local storge :
- ; sd_buff string buffer
- ; sd_char "saved" character
- ; sd_start substring's starting offset
- ; sd_end substring's ending offset
- ; sd_bias row bias
- ; sd_cline cursor line number
- ; sd_ccol cursor column number
- ; sd_nline number of lines in the window
- ; sd_ncols number of columns in the window
- ; sd_ullin upper left corner line number
- ; sd_ulcol upper left corner column number
- ; sd_text text attributes for window
- ; sd_cursv cursor coordinate save area
- ; sd_last last write flag
- ; sd_linum line number
- ; Warning: the following two (2) items are order dependent
- ; sd_wn_si pointer to window object, part 1
- ; sd_wn_es pointer to window object, part 2
-
- SCREENSIZE = 132 shl 1 ; does anybody have more than 132 cols ?
-
- PROC C str_disp USES si di, @@winreg, @@disp, @@end, @@start, @@string
- LOCAL @@winadr:DWORD, @@endofs, @@startofs
- LOCAL $$bias, $$char:BYTE, $$buffer:BYTE:SCREENSIZE
- LOCAL $$linenum:BYTE, $$lastwrite, $$cursorsave, $$textattrib
- LOCAL $$ulcol, $$ullin, $$ncols, $$nline, $$ccol, $$cline
-
- mov [$$lastwrite], 0 ; initialize "last write?" flag
- mov [$$linenum], 0 ; line number
- mov bx, [@@start]
- call getnum ; obtain starting offset
- jc @@toerror
- add ax, OFFSET (TYPE STRDEF).buffer
- mov [@@startofs], ax ; save starting offset
- mov bx, [@@end]
- call getnum ; obtain ending offset
- jc @@toerror
- add ax, OFFSET (TYPE STRDEF).buffer
- cmp ax, [@@startofs] ; is ending offset greater than starting?
- jb @@toerror
- mov [@@endofs], ax ; save ending offset
-
- mov bx, [@@disp]
- cmp [(REG bx).bpage], SPECFIX*2
- je @@jmpnoerror
- @@toerror:
- jmp @@error
- @@jmpnoerror:
- mov ax, [(REG bx).disp]
- mov [$$bias], ax
- call get_port C, [@@winreg], [@@one]
- or ax, ax ; valid port operand?
- jne @@error
- mov si, [tmp_reg.page] ; load a pointer to the port object
- ldpage es, si
- mov si, [tmp_reg.disp]
- mov ax, [(PORTDEF es:si).pflags]
- test ax, PORT_TYPE ; is this port a window?
- jnz @@error
- test ax, WRITE_MODE ; window open for output?
- jnz @@open
- jmp @@return ; if closed, ignore I/O request
- @@open:
- mov ax, [(PORTDEF es:si).curline]
- mov [$$cline], ax
- mov ax, [(PORTDEF es:si).curcol]
- mov [$$ccol], ax
- mov ax, [(PORTDEF es:si).nlines]
- mov [$$nline], ax
- mov ax, [(PORTDEF es:si).ncols]
- mov [$$ncols], ax
- mov ax, [(PORTDEF es:si).ulline]
- mov [$$ullin], ax
- mov ax, [(PORTDEF es:si).ulcol]
- mov [$$ulcol], ax
- mov ax, [(PORTDEF es:si).text]
- mov [$$textattrib], ax
- mov [WORD HIGH @@winadr], es; save pointer to window object
- mov [WORD LOW @@winadr], si
- jmp @@more
-
- @@error:
- restore <si> ; load address of next instruction and
- sub si, 6 ; adjust for 5 operands + opcode
- lea ax, [@@msg]
- push es ; saves es over C call
- call disassemble C, ax, si
- call set_numeric_error C, [@@one], [@@opnd], [tmp_adr]
- pop es
- mov ax, -1 ; signal error
- ret
- DATASEG
- @@msg DB "%SUBSTRING-DISPLAY", 0
- @@one DW 1 ; a constant "one" (1)
- @@opnd DW INVALID_OPERAND_ERROR ; numeric error code
- CODESEG
-
- @@more: ; validate the string operand
- mov bx, [@@string]
- mov si, [(REG bx).page]
- cmp [ptype+si], STRTYPE
- jne @@error
- ldpage es, si
- mov si, [(REG bx).disp]
- sstrlen ax, <es:si>, OVERHEAD
- cmp ax, [@@endofs] ; is ending offset too big?
- jb @@error
- mov dx, [@@endofs] ; Note: [es:si] points to the source string
- add dx, si ; compute ending address
- add si, [@@startofs]
-
- mov cx, [$$ccol] ; translate the string into the local buffer
- mov bx, [$$ncols]
- lea di, [$$buffer]
- push ds
- push ds es ; swap ds and es
- pop ds es
-
- ; Warning: ds does not point to the the data segment in the code which follows
-
- ; Register usage: [es:di] - next character in output buffer
- ; [es:si] - next character in source string
- ; bx - number of columns in window
- ; cx - current column (cursor position) relative to window
- ; dx - end of source string address
- @@next:
- cmp si, dx ; end of input string?
- jae @@final
- lodsb
- cmp al, CTRL_Z ; possible control character?
- ja @@normal
- cmp al, TAB
- jne @@control
-
- mov al, ' ' ; TAB character-- output a series of blanks
- mov ah, cl ; copy cursor position
- sub ah, [$$linenum] ; and adjust for line number
- @@tabloop:
- stosb ; store a blank to the output buffer
- inc cx ; increment the current column number
- inc ah
- test ah, 07h ; is next column a multiple of eight?
- jnz @@tabloop
- jmp @@test
- @@control:
- mov ah, al ; save control character
- mov al, '^' ; load a "^" character and output to buffer
- stosb
- inc cx
- mov al, ah ; copy control character to al and
- add al, '@' ; output the corresponding ASCII char
- @@normal: ; non- control character-- just copy to output buffer
- stosb
- inc cx ; increment the current column number
- @@test:
- cmp cx, bx ; line full?
- jb @@next
-
- call flush ; Full line buffered-- display it on the screen
- mov ax, [$$cline]
- cmp ax, [$$nline] ; are we at the end of the screen?
- jl @@next
- ; Window full-- set cursor position to last line + 1, column 0
- les si, [@@winadr]
- mov [(PORTDEF es:si).curcol], 0
- mov cx, [$$cline]
- mov [(PORTDEF es:si).curline], cx
- jmp @@done
-
- @@final:
- push es ; end of string-- output final line
- les si, [@@winadr]
- mov ax, cx ; save current column
- mov [(PORTDEF es:si).curcol], cx
- mov cx, [$$cline]
- mov [(PORTDEF es:si).curline], cx
- pop es
- mov cx, SCREENSIZE - 1 ; load buffer length
- sub cx, ax ; subtract number of columns in buffer
- mov al, ' '
- rep stosb
- mov [$$lastwrite], 1 ; indicate last line
- call flush ; display to screen
- @@done:
- pop ds
-
- @@return: ; Operation complete-- return to Scheme interpreter
- xor ax, ax ; clear ax = success
- ret
-
- ;************************************************************************
- ;* Local Support: Flush Output Buffer to Screen *
- ;************************************************************************
- PROC NOLANGUAGE flush near
- push ds si di cx dx ; save valuable registers
- push es ; Make ds register point to data segment
- pop ds
-
- inc [$$bias] ; Test for negative bias
- jg @@nobias
- jmp @@skip ; if negative, don't display current line
-
- @@nobias: ; Position the cursor in the current column position
- mov dh, [BYTE $$cline] ; load the current cursor position
- mov dl, [BYTE $$ccol]
- add dh, [BYTE $$ullin]
- add dl, [BYTE $$ulcol]
- mov [$$cursorsave], dx
- xor bh, bh ; page 0 for text-mode
- mov ah, 02h
- int IBM_CRT ; put cursor at current position
- mov cx, [$$ncols]
- sub cx, [$$ccol]
- lea bx, [$$buffer] ; Replace the "last" character in line with an exclamation mark
- cmp [$$lastwrite], 0
- jnz @@lastline ; if last line, leave character alone (jump)
- mov si, cx ; copy character count
- mov al, '!'
-
- xchg al, [bx+si-1]
- mov [$$char], al ; save character to later viewing
- @@lastline:
- mov di, bx ; load buffer offset into di
- mov dx, [$$cursorsave] ; reverse row/column coordinates
- push cx ; save the character counter
- jmp @@inmiddle
- @@loop:
- push cx ; save the character counter
- mov dx, [$$cursorsave] ; load the previous cursor coordinates,
- inc dl ; increment the column number
- mov [$$cursorsave], dx
- xor bh, bh
- mov ah, 02h
- push di
- int IBM_CRT
- pop di
- @@inmiddle:
- mov ah, 09h ; Load "write char w/ attributes" code
- mov al, [BYTE di]
- mov bl, [BYTE $$textattrib] ; load attribute bits
- xor bh, bh ; page # for alpha mode
- mov cx, 1 ; test to see if we buy anything by using a repeat count
- pop dx ; restore character count
- @@more:
- cmp dx, 1 ; more characters to display?
- jle @@bottom ; if no more characters, jump
- cmp al, [BYTE di+1]
- jne @@bottom ; if not same character, jump
- inc cx
- inc di
- inc [BYTE $$cursorsave]
- dec dx ; decrement the character count
- jmp @@more
- @@bottom:
- push dx di
- int IBM_CRT ; write character with attributes
- pop di cx
- inc di ; increment buffer pointer
- loop @@loop
-
- @@back: ; Restore last character in line to its rightful value
- mov si, [$$ncols]
- sub si, [$$ccol]
- mov al, [$$char]
- lea bx, [$$buffer]
- mov [bx+si-1], al
- inc [$$cline] ; Shift buffer to remove the line just displayed
- @@skip:
- mov si, [$$ncols] ; compute number of characters just output
- sub si, [$$ccol] ; (unless bias < 0, in which case we just
- dec si ; branched here)
- push si
- mov cx, 10 ; make up a character count for move
- lea di, [$$buffer]
- add si, di
- rep movsb ; shift any characters left over
- mov bx, [$$ccol] ; save the current column for adjust
- mov [$$ccol], 0
- inc [$$linenum] ; increment formatting line number
-
- ; Reset Active Registers to reflect shifted buffer
- pop ax dx cx di si ; restore char count & control registers
- sub di, ax ; adjust buffer index
- sub cx, ax ; adjust current column
- sub cx, bx
- mov bx, [$$ncols] ; reload line length
- pop ds
- ret
- ENDP flush
-
- ENDP str_disp
-
- ;************************************************************************
- ;* Local Support: Fetch and Validate Integer Argument *
- ;* *
- ;* Input Parameters: bx - address of register containing the integer *
- ;* argument *
- ;* *
- ;* Output Parameters: If CARRY off, normal return: *
- ;* ax - the 16 bit positive integer value *
- ;* If CARRY on, error: *
- ;* ax - the error condition; 0=operand not an *
- ;* integer; 1=integer operand was negative *
- ;* or larger than 16 bits. *
- ;************************************************************************
- PROC getnum near
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@bignum
- mov ax, [(REG bx).disp]
- or ax, ax ; negative?
- js @@badvalue
- clc
- ret
- @@bignum:
- mov si, [(REG bx).page]
- cmp [ptype+si], BIGTYPE ; is argument a bignum?
- jne @@type
- ldpage es, si
- mov si, [(REG bx).disp]
- cmp [(BIGDEF es:si).data.sign], 0
- jne @@badvalue
- cmp [(BIGDEF es:si).data.len], OFFSET (TYPE BIGDEF).data.lsw + (TYPE WORD) + 1
- jne @@badvalue
- mov ax, [(BIGDEF es:si).data.lsw]; load 16 bit value of bignum
- clc
- ret
- @@type:
- mov ax, 0 ; indicate operand wrong type
- stc
- ret
- @@badvalue:
- mov ax, 1
- stc
- ret
- ENDP getnum
-
- ;************************************************************************
- ;* Local Support: Return a 16 bit positive integer value *
- ;* *
- ;* Input Parameters: bx - address of destination register *
- ;* si - 16 bit unsigned integer value to be returned *
- ;* *
- ;* Output Parameters: The Scheme representation of the 16 bit unsigned *
- ;* value is placed into the destination register. *
- ;************************************************************************
- PROC retnum near
- cmp si, 07fffh ; can result be represented as a fixnum?
- ja @@makebig
- mov [(REG bx).bpage], SPECFIX*2 ; return a fixnum result
- mov [(REG bx).disp], si
- ret
- @@makebig:
- push si
- push bx
-
- mov cx, 1+2 ; load size of bignum desired
- mov ax, BIGTYPE
- call alloc_block C, bx, ax, cx
-
- pop bx ; restore destination reg
- mov si, [(REG bx).page]
- ldpage es, si
- mov si, [(REG bx).disp]
- mov [(BIGDEF es:si).data.sign], 0
- pop [(BIGDEF es:si).data.lsw] ; store value into the bignum
- ret
- ENDP retnum
-
- END